﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CameraService;
using Com.Mc.Common.Cameras.Common;
using Com.Mc.Common.Cameras;
using Com.Mc.Common.Base.Sockets;
using System.Configuration;
using PluginService.Model;
using Com.Mc.Common.Base.JsonFileReader;
using AopFaceDeteive;
using CommonProjects.FaceDetetive;
using CommonProjects.FaceDetetive.EventArgs;
using CommonProjects.FaceFeatureContex;
using Common.Logging;
using NamedPipeWrapper;
using FaceCoreBase.Models;
using System.Drawing;
using PluginService.Common;
using System.Xml;
using PluginService.Common.Model;
using PluginService.Base;

namespace PluginService
{
    public abstract class FaceDeteiveServiceHelper:IDisposable
    {
        #region 变量

        protected static log4net.ILog _log = log4net.LogManager.GetLogger(typeof(FaceDeteiveServiceHelper));
       
        protected List<DisplayAndAlarmConfig> _displayAndAlarmConfig = null;
        protected IFaceDeteiveManager _faceDeteiveManager;

        protected AsyncFunc<string, byte[], CameraInfor, int> _asyncPipeSend;
        protected AsyncFunc<string, byte[], FaceDeteiveFeatureResult> _asyncFaceDeteive;

        protected NamedPipeServer<CommandModel> _commandPipeServer = new NamedPipeServer<CommandModel>(Consts.CONTROLL_PIPE_NAME);

        protected CameraManager _cameraManager = new WebServerCameraManager();

        #endregion

        #region 公共方法

        public virtual void Init()
        {
            
            InitAsync();
            string path=null;
            try
            {
                _commandPipeServer.ClientMessage += new ConnectionMessageEventHandler<CommandModel, CommandModel>(OnReceivedClientMessage);
                _commandPipeServer.ClientConnected += new ConnectionEventHandler<CommandModel, CommandModel>(CommandPipeServer_ClientConnected);
                _commandPipeServer.ClientDisconnected += new ConnectionEventHandler<CommandModel, CommandModel>(CommandPipeServer_ClientDisconnected);
                _commandPipeServer.Error += new PipeExceptionEventHandler(CommandPipeServer_Error);
                
                string pluginServicePath = Util.GetWindowsServiceInstallPath("PluginService");
                path = pluginServicePath.Replace("PluginService.exe","");
                
            }
            catch (Exception ex)
            {
                _log.Error(ex);
            }

            if (!string.IsNullOrEmpty(path))
            {
                //InitDisplayAndAlarmConfig(path);
                _cameraManager.Init(path);
                _cameraManager.OnReceivedImage += new OnReceivedImage(OnReceivedImageHander);
                InitConntection();
                InitFaceDeteive(path);
                InitBlankData();
            }
        }

        

        public virtual void Start()
        {
            try
            {
                _commandPipeServer.Start();
            }
            catch (Exception ex)
            {
                _log.Error(ex);
            }

        }

        #endregion

        #region 受保护函数

        protected virtual void CommandPipeServer_ClientDisconnected(NamedPipeConnection<CommandModel, CommandModel> connection)
        {
            _log.Info("客户端退出");
            HandPauseCommand();
        }

        protected virtual void CommandPipeServer_ClientConnected(NamedPipeConnection<CommandModel, CommandModel> connection)
        {
            _log.Info("客户端接入");
            HandStartCommand();
            HandReloadCommand();
        }

        protected virtual void CommandPipeServer_Error(Exception exception)
        {
            _log.Error(exception);
        }

        protected virtual void OnReceivedClientMessage(NamedPipeConnection<CommandModel, CommandModel> connection, CommandModel message)
        {
            if (message!=null)
            {
                
                switch (message.CommandType)
                {
                    case CommandType.Start:
                        HandStartCommand();
                        break;
                    case CommandType.Stop:
                        HandStopCommand();
                        break;
                    case CommandType.Pause:
                        HandPauseCommand();
                        break;
                    case CommandType.Reload:
                        HandReloadCommand();
                        break;
                    case CommandType.GetCameraConfig:
                        HandGetCameraConfig();
                        break;
                    case CommandType.UpdateCameraConfig:
                        HandUpdateCameraConfig(message);
                        break;
                    case CommandType.UpdateAppConfig:
                        HandUpdateAppConfig(message);
                        break;
                }
            }
        }

        protected virtual void HandUpdateAppConfig(CommandModel message)
        {
            if (message != null && message.CommandBody != null)
            {
                try
                {
                    var setings=Newtonsoft.Json.JsonConvert.DeserializeObject<List<AppConfigKeyValueItem>>(message.CommandBody);
                    foreach(var seting in setings)
                    {
                        RefreshFaceDeteiveConfig(seting.Key, seting.Value);
                        SaveAndUpdateConfig(seting.Key,seting.Value);
                    }
                    _commandPipeServer.PushMessage(new CommandModel(){
                        CommandBody=Newtonsoft.Json.JsonConvert.SerializeObject( new CommandResult(){
                            Result=true,
                            OrginCommandModel=message
                        }),
                        CommandType=CommandType.UpdateAppConfig
                    });
                }
                catch (Exception ex)
                {
                    _commandPipeServer.PushMessage(new CommandModel(){
                        CommandBody=Newtonsoft.Json.JsonConvert.SerializeObject( new CommandResult(){
                            Result=false,
                            OrginCommandModel=message,
                            Error=ex.Message
                        }),
                        CommandType=CommandType.UpdateAppConfig
                    });
                    _log.Error(ex);
                }
            }
        }

        protected virtual void HandUpdateCameraConfig(CommandModel message)
        {
            if (message != null && message.CommandBody!=null)
            {
                try
                {

                    var result = _cameraManager.UpdateCameraConfig(message.CommandBody);
                    _commandPipeServer.PushMessage(new CommandModel()
                    {
                        CommandBody = Newtonsoft.Json.JsonConvert.SerializeObject(new CommandResult()
                        {
                            Result = result,
                            OrginCommandModel = message,
                        }),
                        CommandType = CommandType.UpdateAppConfig
                    });
                    
                }
                catch(Exception ex)
                {

                    _log.Error("更新配置文件失败");
                    _log.Error(ex);
                    _commandPipeServer.PushMessage(new CommandModel()
                    {
                        CommandBody = Newtonsoft.Json.JsonConvert.SerializeObject(new CommandResult()
                        {
                            Result = false,
                            OrginCommandModel = message,
                            Error = ex.Message
                        }),
                        CommandType = CommandType.UpdateAppConfig
                    });
                }
               
            }
        }

        protected virtual void HandGetCameraConfig()
        {
            var entiys = _cameraManager.CameraEntitys;
            _commandPipeServer.PushMessage(new CommandModel() { 
                CommandType=CommandType.GetCameraConfig,
                CommandBody=Newtonsoft.Json.JsonConvert.SerializeObject(entiys)
            });
        }

        protected virtual void HandPauseCommand()
        {
            _cameraManager.Suspend();
            _faceDeteiveManager.Suspend();
        }

        protected virtual void HandReloadCommand()
        {
            _faceDeteiveManager.Resume();
            _cameraManager.Resume();
            
        }

        protected virtual void HandStopCommand()
        {
 
        }

        protected virtual void HandStartCommand()
        {

            try
            {
                _cameraManager.Start();
                if (_faceDeteiveManager != null && !_faceDeteiveManager.Started)
                {
                    _faceDeteiveManager.Start();
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex);
            }

        }

        #endregion

        #region 私有函数

        private void SaveAndUpdateConfig(string key, string value)
        {
            if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
            {
                Configuration cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                var appSetingValue = cfa.AppSettings.Settings[key].Value;
                if (string.IsNullOrEmpty(appSetingValue))
                {
                    cfa.AppSettings.Settings.Add(key, value);
                }
                else
                {
                    cfa.AppSettings.Settings[key].Value = value;
                }
                cfa.Save();
                ConfigurationManager.RefreshSection("appSettings");
            }
            
        }

        private void RefreshFaceDeteiveConfig(string key, string value)
        {
            if (_faceDeteiveManager != null)
            {
                switch (key)
                {
                    case "threshold":
                        _faceDeteiveManager.Threshold = (float)Convert.ToSingle(value);
                        break;
                    case "thread_sleep_time":
                        _faceDeteiveManager.ThreadSleetTime = Convert.ToInt32(value);
                        break;
                    case "max_face_count":
                        _faceDeteiveManager.MaxDetetiveFaceCount = Convert.ToInt32(value);
                        break;
                }
            }
            
        }

        private void AddAppConfig(string key, string value)
        {
 
        }

        private void InitDisplayAndAlarmConfig(string path)
        {
            if (_displayAndAlarmConfig == null)
            {
                try
                {
                    _displayAndAlarmConfig = JsonFileReader<List<DisplayAndAlarmConfig>>.GetObject(path + "Config\\DisplayAndAlarmConfig.json");
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                }
            }
        }

        #endregion

        #region 抽象方法

        
        protected abstract void SendImageData(string id, byte[] data, CameraInfor info);

        protected abstract void SendCompareResult(FaceCmpResultArgs args);

        protected abstract void InitConntection();

        protected abstract void InitBlankData();

        

        #endregion

        #region 受保护函数

        protected virtual void InitAsync()
        {
            _asyncPipeSend = new AsyncFunc<string, byte[], CameraInfor, int>(AsyncSendFunc);
            _asyncFaceDeteive = new AsyncFunc<string, byte[], FaceDeteiveFeatureResult>(DeteiveFace);
            _asyncFaceDeteive.Completed += new AsyncFuncCompletedEventHandler<FaceDeteiveFeatureResult>(AsyncFaceDeteive_Completed);
        }

        protected virtual void AsyncFaceDeteive_Completed(object sender, AsyncFuncCompletedEventArgs<FaceDeteiveFeatureResult> e)
        {
            if (e.Error != null)
            {
                _log.Error(e.Error);
                return;
            }
            if (e.Cancelled)
                return;

            var feature = e.Result;

            if (feature != null)
            {
                foreach (var f in feature.FaceModelRectangles)
                {
                    if (f.FaceModel != null && f.FaceModel.Feature != null)
                    {
                        byte[] data1 = null;
                        if (e.Result.ImageBytes != null)
                        {
                            data1 = new byte[e.Result.ImageBytes.Length];
                            Array.Copy(e.Result.ImageBytes, data1, data1.Length);
                        }
                        var stateFaceStateItem = new FaceFeatureStateItem(Guid.NewGuid().ToString(), data1, f.FaceModel.Feature, new DateTime());
                        _faceDeteiveManager.AddTargetCacheItem(stateFaceStateItem);
                    }
                }
            }
        }

        protected virtual int AsyncSendFunc(string id, byte[] data, CameraInfor camerainfo)
        {
            SendImageData(id, data, camerainfo);
            return 0;
        }

        
        protected virtual void InitFaceDeteive(string path)
        {
            int threadCount = 1;
            int maxFaceCount=10;
            try
            {
                threadCount = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["thread_count"]);
                maxFaceCount=Convert.ToInt32(ConfigurationManager.AppSettings["max_face_count"]);
                float threshold=Convert.ToSingle(ConfigurationManager.AppSettings["threshold"]);
                int sleepTime=Convert.ToInt32(ConfigurationManager.AppSettings["thread_sleep_time"]);
                bool isNoticeFailed=Convert.ToBoolean(ConfigurationManager.AppSettings["is_noticed_compare_failed"]);
                _faceDeteiveManager = new AopFaceDeteiveManager(threadCount, threshold, maxFaceCount,  sleepTime, isNoticeFailed, path + "Config\\Engine.xml");
                _faceDeteiveManager.OnTopCompareSuccessHander += new TopCompareSuccessHander(FaceDeteiveManager_OnTopCompareSuccessHander);
                //_faceDeteiveManager.Init();
                
            }
            catch (Exception ex)
            {
                _log.Error(ex);
                //throw ex;
            }

            
        }

        protected virtual void FaceDeteiveManager_OnTopCompareSuccessHander(CommonProjects.FaceDetetive.EventArgs.FaceCmpResultArgs args)
        {
            if (args != null)
            {
                SendCompareResult(args);
            }
        }

        protected virtual void OnReceivedImageHander(ICapture capture,CaptureImageData imageData)
        {
            if (imageData != null&&imageData.ImageArray!=null)
            {
                byte[] data1 = new byte[imageData.ImageArray.Length];
                Array.Copy(imageData.ImageArray, data1, data1.Length);
                byte[] data2 = new byte[imageData.ImageArray.Length];
                Array.Copy(imageData.ImageArray, data2, data2.Length);
                var camerid = capture.CameraInfo.DeviceId;

                _asyncPipeSend.TryInvokeAsync(camerid, data1, capture.CameraInfo);

                _asyncFaceDeteive.TryInvokeAsync(camerid, data2);
            }
        }

        protected virtual FaceDeteiveFeatureResult DeteiveFace(string camerId,byte[] imageData)
        {
            if (_faceDeteiveManager != null && imageData!=null)
            {
                return _faceDeteiveManager.GetFaceFeature(imageData);
                
            }
            return null;

        }
        #endregion

        #region IDispose
        
        public void Dispose()
        {
            _cameraManager.Dispose();
            if (_asyncPipeSend != null)
            {
                _asyncPipeSend.Cancel();
            }

            if (_asyncFaceDeteive != null)
            {
                _asyncFaceDeteive.Cancel();
            }

            if (_faceDeteiveManager != null)
            {
                _faceDeteiveManager.Stop();
                _faceDeteiveManager.Dispose();
            }
        }

        #endregion
    }
}
